import 'dart:async';
import 'dart:convert';

import 'package:bruno/bruno.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:xml/xml_events.dart';
import 'package:yt_devops/configs.dart';
import 'package:yt_devops/pages/devices/device_controll/component/rate_setting/rate_setting_model.dart';
import 'package:yt_devops/pages/devices/device_controll/component/rate_setting/rate_util.dart';
import 'package:yt_devops/resources/str_res_keys.dart';
import 'package:yt_devops/routers/router_path.dart';
import 'package:yt_devops/services/device/device_sevices.dart';
import 'package:yt_devops/utils/brn_row1_delegate.dart';
import 'package:yt_devops/utils/extensions.dart';
import 'package:yt_devops/utils/func_utils.dart';

const int TIMEPERIODNUM = 8;
const int RATENUM = 6;
const int TABLENUM = 14;

class RateSettingController extends GetxController {
  late int deviceId;
  late bool isEdit;
  List<TimeZoneData> timeZoneData = [];
  List<List<TimePeriodData>> timePeriodTable = [];
  List<bool> expandedAll = List.generate(TIMEPERIODNUM, (index) => false);
  DeviceServices deviceServices = Get.put(DeviceServices());

  List<String> timeOptions = List.generate(
    TIMEPERIODNUM,
    (index) =>
        '${FuncUtils.formatMessage(resKey: ResKey.timePeriodTable, defaultMessage: '时段表')}${index + 1}',
  );

  List<String> rateOptions = List.generate(
    RATENUM,
    (index) => 'T${index + 1}',
  );

  initData(int id, bool edit) {
    deviceId = id;
    isEdit = edit;
    getRateSetting();
  }

  init() {
    timeZoneData = List.generate(
      TABLENUM,
      (index) => TimeZoneData(index: index + 1),
    );
    timePeriodTable = List.generate(
      TIMEPERIODNUM,
      (index) => List.generate(
        TABLENUM,
        (index) => TimePeriodData(index: index + 1),
      ),
    );
  }

  changeExpanded(int index, bool expand) {
    expandedAll[index] = expand;
    update();
  }

  getRateSetting() {
    deviceServices.getRateSetting({
      'deviceId': deviceId,
      'key': 'm33',
    }).then((onValue) {
      late Map<String, dynamic> data;
      try {
        data = jsonDecode(
            //'{\"m34\":[{\"Tn\":1,\"Md\":\"01-01\"}],\"m35\":[{\"Tn\":1,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]},{\"Tn\":2,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]},{\"Tn\":3,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]},{\"Tn\":4,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]},{\"Tn\":5,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]},{\"Tn\":6,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]},{\"Tn\":7,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]},{\"Tn\":8,\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}]}]}' ??
            // '{\"m34\":[{\"Tn\":3,\"Md\":\"01-01\"}],\"m35\":[{\"m36\":[{\"m37\":1,\"Hm\":\"00:00\"}],\"Tn\":1},{\"m36\":[{\"m37\":2,\"Hm\":\"00:00\"},{\"m37\":4,\"Hm\":\"02:00\"}],\"Tn\":3}]}' ??
            onValue?['data'].toString() ?? '{}') ?? {};
      } catch (e) {
        data = {};
      }
      if (isEdit) {
        timeZoneData[0].Md = '01-01';
        timePeriodTable.forEach((timePeriod) {
          timePeriod[0].Hm = '00:00';
        });
      }
      int index = 0;
      data['m34']?.forEach((item) {
        timeZoneData[index].Tn = item['Tn'];
        timeZoneData[index].Md = item['Md'];
        index++;
      });
      data['m35']?.forEach((item) {
        int elementIndex = 0;
        item['m36']?.forEach((element) {
          timePeriodTable[item['Tn'] - 1][elementIndex].m37 = element['m37'];
          timePeriodTable[item['Tn'] - 1][elementIndex].Hm = element['Hm'];
          elementIndex++;
        });
      });
      update();
    });
  }

  goSetting() {
    Get.toNamed(
      RouterPath.rateSetting,
      arguments: {
        'deviceId': deviceId,
      },
    );
  }

  selectColClick(String type, int tableIndex, int rowIndex) {
    late String title;
    late List<String> options;
    late int selectedIndex;
    if (type == 'timePeriod') {
      title = FuncUtils.formatMessage(
          resKey: ResKey.timePeriodTable, defaultMessage: '时段表');
      options = timeOptions;
      selectedIndex = timeZoneData[rowIndex].Tn ?? 1;
    } else {
      title =
          FuncUtils.formatMessage(resKey: ResKey.rate, defaultMessage: '费率');
      options = rateOptions;
      selectedIndex = timePeriodTable[tableIndex][rowIndex].m37 ?? 1;
    }
    selectedIndex--;
    BrnMultiDataPicker(
      context: Get.context!,
      title: title,
      delegate: Brn1RowDelegate(
        options,
        firstSelectedIndex: selectedIndex,
      ),
      confirmClick: (indexList) {
        if (indexList.isNotEmpty) {
          int index = indexList[0];
          if (type == 'timePeriod') {
            timeZoneData[rowIndex].Tn = index + 1;
          } else {
            timePeriodTable[tableIndex][rowIndex].m37 = index + 1;
          }
          update();
        }
      },
    ).show();
  }

  timeColClick(String type, int tableIndex, int rowIndex) {
    late BrnDateTimePickerMode mode;
    late String format;
    late DateTime initialValue;
    if (type == 'date') {
      mode = BrnDateTimePickerMode.date;
      format = 'MM-dd';
      String md = timeZoneData[rowIndex].Md ?? '01-01';
      initialValue = DateTime.parse('2024-$md');
    } else {
      mode = BrnDateTimePickerMode.time;
      format = 'HH:mm';
      String hd = timePeriodTable[tableIndex][rowIndex].Hm ?? '00:00';
      initialValue = DateTime.parse('2024-01-01 $hd');
    }
    BrnDatePicker.showDatePicker(
      Get.context!,
      pickerMode: mode,
      dateFormat: format,
      initialDateTime: initialValue,
      onConfirm: (date, list) {
        if (type == 'date') {
          String md = DateFormat('MM-dd').format(date);
          timeZoneData[rowIndex].Md = md;
        } else {
          String hm = DateFormat('HH:mm').format(date);
          timePeriodTable[tableIndex][rowIndex].Hm = hm;
        }
        update();
      },
    );
  }

  Map<String, dynamic> getInputData() {
    List<Map<String, dynamic>?> m34 = timeZoneData
        .map((e) => (e.Md ?? e.Tn) != null ? e.toJson(true) : null)
        .toList();
    m34.removeWhere((e) => e == null);

    List<Map<String, dynamic>?> m35 = timePeriodTable.mapIndexed((e, index) {
      List<Map<String, dynamic>?> result = e
          .mapIndexed((e, rowIndex) =>
              ((rowIndex == 0 ? e.m37 : (e.Hm ?? e.m37)) != null)
                  ? e.toJson(true)
                  : null)
          .toList();
      result.removeWhere((e) => e == null);
      return result.isEmpty ? null : {'m36': result, 'Tn': index + 1};
    }).toList();
    m35.removeWhere((e) => e == null);
    return {
      'm34': m34,
      'm35': m35,
    };
  }

  Future<bool> submit() async {
    Completer<bool> completer = Completer();
    Future<bool> future = completer.future;
    if (!validate(timeZoneData, timePeriodTable)) {
      completer.completeError(false);
    } else {
      Configs.httpClient.requestWithLoading(
        () async {
          await DeviceServices().editRateSetting({
            'deviceId': deviceId,
            'serviceId': 'm33',
            'input': jsonEncode(getInputData()),
          });
          FuncUtils.requestTipsDislog(
            Get.context,
            ResKey.executeSuccess.tr,
            true,
            duration: const Duration(microseconds: 1000),
          ).then((value) {
            completer.complete(true);
          });
        },
        onError: (err) {
          FuncUtils.requestTipsDislog(
            Get.context,
            ResKey.executeFailure.tr,
            false,
            duration: const Duration(
              milliseconds: 1000,
            ),
          );
          completer.completeError(false);
          return true;
        },
        showLoading: true,
      );
    }
    return future;
  }

  @override
  void onInit() {
    init();
    super.onInit();
  }

  @override
  void onReady() {}

  @override
  void onClose() {}
}
